Swift4 新特性

Codeable

不得不说OC 中的序列化和反序列化工作确实是一件麻烦事, 虽然可以使用 Runtime 优化, 但是还是不够优雅, 而且容易出错;
Swift 4 中的 Codable 协议可以让这些烦恼一去不复返;
使用起来很简单, 遵循这个协议不用多添加任何代码:

struct Person {
var name: String
var age: Int
}
// 只要类型中的属性遵循 Codable 协议, 那么这个类型就可以遵循 Codeable 协议
struct Book {
let price: Double
let authors: [Person]
}
// 编码, 解码
let dic = ["name": "foo", "age": 18] as [String : Any]
let data = try! JSONSerialization.data(withJSONObject: dic, options: [])
let person = try? JSONDecoder().decode(Person.self, from: data)
// 当然也可以自定义 Key
struct Person: Codable {
let name: String
let age: Int?
enum CodingKeys: String, CodingKey {
case name = "title"
case age
}
}

更多用法参见 官方文档

单边 Range

在 Swift 4 中添加了 3 种 Range 操作符:

  • ..<i,对应s.prefix(upTo:),表达从集合开始到i的半闭半开区间;
  • ...i,对应s.prefix(through:),表达从集合开始到i的闭区间;
  • i...,对应s.suffix(from: i),表达从i开始到集合结束的半闭半开区间;

String

Swift 4 中 String 重新变成了一个 Collection 类型, 所以对 Collection 类型的所有操作, 都能作用在 String 上了,

let greeting = "Hello Mars"
greeting.count // 10
let spaceIndex = greeting.index(of: " ")! // 5
let substring = greeting[..<spaceIndex] // Hello

另外, 在 Swift 4 中还增加了多行字符串, 这和 JavaScript ES6 中的 `` 多行字符串有点类似, 但是是通过三对引号括起来的

let xmlInfo = """
<?xml version="1.0"?>
<episode id="1">
<title>String is a collection again</title>
<author>11</author>
<created_at>2017-05-18</created_at>
</episode>
"""

更智能的 KVC

KVC ( Key-Value-Coding ) 一直是 Cocoa 中很重要的一个特性, 但是由于历史原因, 在 Swift 中使用有很大的局限性, 比如必须要是NSObject 的派生类, 而且value(forKeyPath:)方法返回的类型是Any?, 类型也不安全, 但是在 Swift4 中有了全新的 KVC:

class Foo {
var bar = "bar"
var baz = [1, 2, 3, 4]
}
struct Foo {
var bar = "bar"
var baz = [1, 2, 3, 4]
}
let barKeyPath = \Foo.bar
var bar = foo[keyPath: barKeyPath]
foo[keyPath: barKeyPath] = "BAR"

可以看出, 既不需要派生自NSObject 也不需要添加@objc, 同时还支持 struct;

用多个 protocol 来约束类型

在 Swift3 中是不能使用多个 protocol 来约束类型的, 所以在碰到OC 中这样的id<Protocol1, Protocol2> 代码是无能为力的;
Swift 4 解决了这个问题, 可以使用& 符号连接多个 protocol 或者 class ;

protocol P {}
struct S : P {}
class C : P {}
class D { }
class E: D, P { }
let u: AnyObject & P = C() // 可以使用 AnyObject 表示任意一个类, 表示 u 是一个遵循了P 协议个类
let v: D & P = E() // 也可以使用具体的类名来约束

其他新特性

  • swapAt() 方法
  • subscript 方法中可以使用泛型
  • 改进 private 的访问权限
    private 属性在 extension 中可以使用;